#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
字符串相似度计算工具
用于计算两个字符串之间的相似度，主要用于目录名称比较
"""

import logging

logger = logging.getLogger(__name__)


def calculate_edit_distance(str1: str, str2: str) -> int:
    """
    计算两个字符串之间的编辑距离（Levenshtein Distance）
    
    Args:
        str1: 第一个字符串
        str2: 第二个字符串
        
    Returns:
        int: 编辑距离
    """
    if not str1 and not str2:
        return 0
    if not str1:
        return len(str2)
    if not str2:
        return len(str1)
    
    # 创建动态规划矩阵
    rows = len(str1) + 1
    cols = len(str2) + 1
    dp = [[0] * cols for _ in range(rows)]
    
    # 初始化边界条件
    for i in range(rows):
        dp[i][0] = i
    for j in range(cols):
        dp[0][j] = j
    
    # 填充动态规划矩阵
    for i in range(1, rows):
        for j in range(1, cols):
            if str1[i-1] == str2[j-1]:
                dp[i][j] = dp[i-1][j-1]  # 字符相同，无需操作
            else:
                dp[i][j] = min(
                    dp[i-1][j] + 1,    # 删除
                    dp[i][j-1] + 1,    # 插入
                    dp[i-1][j-1] + 1   # 替换
                )
    
    return dp[rows-1][cols-1]


def calculate_similarity_percentage(str1: str, str2: str, case_sensitive: bool = False) -> float:
    """
    计算两个字符串的相似度百分比
    
    Args:
        str1: 第一个字符串
        str2: 第二个字符串
        case_sensitive: 是否区分大小写，默认不区分
        
    Returns:
        float: 相似度百分比 (0-100)
    """
    if not case_sensitive:
        str1 = str1.lower()
        str2 = str2.lower()
    
    # 处理空字符串情况
    if not str1 and not str2:
        return 100.0
    if not str1 or not str2:
        return 0.0
    
    # 计算编辑距离
    edit_distance = calculate_edit_distance(str1, str2)
    
    # 计算相似度百分比
    max_length = max(len(str1), len(str2))
    if max_length == 0:
        return 100.0
    
    similarity = (1 - edit_distance / max_length) * 100
    return max(0.0, similarity)  # 确保不返回负数


def calculate_directory_name_similarity(dir1: str, dir2: str) -> float:
    """
    计算两个目录名称的相似度
    专门用于目录名称比较，包含一些预处理逻辑
    
    Args:
        dir1: 第一个目录名称
        dir2: 第二个目录名称
        
    Returns:
        float: 相似度百分比 (0-100)
    """
    # 提取目录的基本名称（去除路径）
    import os
    name1 = os.path.basename(dir1.strip())
    name2 = os.path.basename(dir2.strip())
    
    # 预处理：移除常见的版本号、括号内容等
    def preprocess_name(name: str) -> str:
        import re
        # 移除括号及其内容
        name = re.sub(r'\([^)]*\)', '', name)
        # 移除方括号及其内容
        name = re.sub(r'\[[^\]]*\]', '', name)
        # 移除常见的版本号模式
        name = re.sub(r'v?\d+\.\d+(\.\d+)?', '', name)
        # 移除多余的空格和特殊字符
        name = re.sub(r'[_\-\s]+', ' ', name).strip()
        return name
    
    processed_name1 = preprocess_name(name1)
    processed_name2 = preprocess_name(name2)
    
    # 如果预处理后的名称为空，使用原始名称
    if not processed_name1:
        processed_name1 = name1
    if not processed_name2:
        processed_name2 = name2
    
    similarity = calculate_similarity_percentage(processed_name1, processed_name2)
    
    logger.debug(f"目录相似度计算: '{name1}' vs '{name2}' -> {similarity:.2f}%")
    return similarity


def is_similar_by_threshold(str1: str, str2: str, threshold: float = 95.0) -> bool:
    """
    根据阈值判断两个字符串是否相似
    
    Args:
        str1: 第一个字符串
        str2: 第二个字符串
        threshold: 相似度阈值 (0-100)
        
    Returns:
        bool: 是否相似
    """
    similarity = calculate_directory_name_similarity(str1, str2)
    return similarity >= threshold


if __name__ == '__main__':
    # 测试代码
    test_pairs = [
        ("Documents", "Documents"),
        ("Music Files", "Music_Files"),
        ("Video [HD]", "Video"),
        ("Photos v2.0", "Photos"),
        ("项目文档", "项目文档备份"),
        ("Program Files", "Program Files (x86)"),
    ]
    
    print("字符串相似度测试:")
    for str1, str2 in test_pairs:
        similarity = calculate_directory_name_similarity(str1, str2)
        print(f"'{str1}' vs '{str2}': {similarity:.2f}%")
        
        for threshold in [95, 90, 85, 80]:
            is_similar = is_similar_by_threshold(str1, str2, threshold)
            print(f"  阈值{threshold}%: {'相似' if is_similar else '不相似'}")
        print()